#include "jstypes.h"
#include "y.tab.h"
#include <glib.h>
#include "lex.yy.h"
JSNode* print (JSNode *node, char *pref, char **code)
{
	char *pr = g_strconcat(pref, "\t", NULL);
	JSNode *iter;
	gchar *in;
	*code = g_strdup ("");
if (node == NULL)
	return node;
	printf ("%s%d\n",pref,node->pn_type);
	switch (node->pn_arity)
	{
		case PN_UNARY:
			printf ("%sUNARY\n", pref);
			switch ((JSTokenType)node->pn_type)
			{
			case TOK_SEMI:
				print (node->pn_u.unary.kid, pr, code);
				*code = g_strconcat (*code, ";", NULL);
				break;
			}
			break;
		case PN_LIST:
			printf ("%sLIST\n", pref);
			switch ((JSTokenType)node->pn_type)
			{
			case TOK_LP:
				print (node->pn_u.list.head, pr, code);
				*code = g_strconcat (*code, "(", NULL);
				int k = 0;
				for (iter = ((JSNode*)node->pn_u.list.head)->pn_next; iter != NULL; iter = iter->pn_next, k++)
				{
					print (iter, pr, &in);
					if (k)
						*code = g_strconcat (*code, ", ", in, NULL);
					else
						*code = g_strconcat (*code, in, NULL);
				}

				*code = g_strconcat (*code, ")", NULL);
				break;
			case TOK_RC:
				{
				print (node->pn_u.list.head, pr, code);
				*code = g_strconcat (*code, "(", NULL);
				int k = 0;
				for (iter = ((JSNode*)node->pn_u.list.head)->pn_next; iter != NULL; iter = iter->pn_next, k++)
				{
					print (iter, pr, &in);
					if (k)
						*code = g_strconcat (*code, ", ", in, NULL);
					else
						*code = g_strconcat (*code, in, NULL);
				}
}
				*code = g_strconcat (*code, ")", NULL);
				break;
			case TOK_LC:
				*code = g_strdup ("{");
				for (iter = node->pn_u.list.head; iter != NULL; iter = iter->pn_next)
				{
					print (iter, pr, &in);
					*code = g_strconcat (*code, in, "\n", NULL);				
				}
				*code = g_strconcat (*code, "}", NULL);
				break;
			case TOK_NEW:
				///NOT COMPLETE
				print (node->pn_u.list.head, pr, code);
				*code = g_strconcat (*code, " ( ", NULL);
				k = 0;
				for (iter = ((JSNode*)node->pn_u.list.head)->pn_next; iter != NULL; iter = iter->pn_next)
				{
					print (iter, pr, &in);
					if (k)
						*code = g_strconcat (*code,", ", in, NULL);
					else
						*code = g_strconcat (*code, in, NULL);
					k++;
				}
				*code = g_strconcat (*code, " )", NULL);
				break;
			}
			break;
		case PN_BINARY:
			printf ("%sBINARY\n", pref);
			switch ((JSTokenType)node->pn_type)
			{
				case TOK_ASSIGN:
					///NOT COMPLETE
					print (node->pn_u.binary.left, pr, code);
					print (node->pn_u.binary.right, pr, &in);

					*code = g_strconcat (*code, " = ", in, NULL);
					
					break;
			}
			break;
		case PN_FUNC:
			printf ("%sFUNC\n", pref);

/*			JSObject * object = ATOM_TO_OBJECT(node->pn_funAtom);
			JSFunction * function = (JSFunction *) JS_GetPrivate(context, object);

			*code = g_strconcat (*code, " function ", NULL);

			if (function->atom) {
				*code = g_strconcat (*code, js_AtomToPrintableString(context, function->atom), NULL);
			}

			*code = g_strconcat (*code, " (", NULL);
			/* function parameters */
/*			JSAtom ** params = malloc(function->nargs * sizeof(JSAtom *));
			int i;
			for (i = 0; i < function->nargs; i++) {
			    /* initialize to NULL for sanity check */
/*			    params[i] = NULL;
			}
			JSScope * scope = OBJ_SCOPE(object);
			JSScopeProperty * scope_property;
			for (scope_property = SCOPE_LAST_PROP(scope);
			        scope_property != NULL;
			        scope_property = scope_property->parent) {
			    if (!JSID_IS_ATOM (scope_property->id) || ((uint16)scope_property->shortid) >= function->nargs) {
			    continue;
			    }
			    params[(uint16) scope_property->shortid] = JSID_TO_ATOM(scope_property->id);
			}
			int k = 0;
			for (i = 0; i < function->nargs; i++) {
			    assert(params[i] != NULL);
				if (!k)
					*code = g_strconcat (*code, js_AtomToPrintableString(context, params[i]), NULL);
				else
					*code = g_strconcat (*code, ", ", js_AtomToPrintableString(context, params[i]), NULL);
				k++;
		      /* params[i] is a JSAtom * containing the function name */
//		    }
/*			*code = g_strconcat (*code, " ){}", NULL);
		    free(params);
*/
//			node->pn_u.func.flags = TCF_COMPILING;
			break;
		case PN_NAME:
			printf ("%sNAME\n%s\n", pref, node->pn_u.name.name);
/*			JSAtom * atom = node->pn_atom;
			*code = js_AtomToPrintableString(context, node->pn_atom);			*/
			break;
		case PN_NULLARY:
			printf ("%sNULL\n", pref);
			switch ((JSTokenType)node->pn_type)
			{
				case TOK_STRING:
//					*code = g_strconcat ("\"", js_AtomToPrintableString(context, node->pn_atom), "\"", NULL);			
					break;
				case TOK_NUMBER:
//					*code = g_new (char, 100);
//					sprintf (*code, "%lf", node->pn_u.dval);
					break;
			}
			break;
		case PN_TERNARY:
			printf ("%sTERNARY\n", pref);
/*			print (node->pn_u.ternary.kid1, pr, &in);
			print (node->pn_u.ternary.kid2, pr, &in);			
			print (node->pn_u.ternary.kid3, pr, &in);			*/
			break;
		
	}
	g_free (pr);
	return node;
}


int main ()
{
global = NULL;
	FILE *f = fopen ("main.js", "r");
YY_BUFFER_STATE b = yy_create_buffer (f,10000);
yy_switch_to_buffer (b);
	printf ("%d", yyparse ());
//	printf ("00%d00\n", global);
gchar *cd;
print (global, "|", &cd);
}
